package com.tianji.learning.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.dto.IdAndNumDTO;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.domain.query.PageQuery;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.DateUtils;
import com.tianji.common.utils.StringUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.po.LearningLesson;
import com.tianji.learning.domain.po.LearningRecord;
import com.tianji.learning.domain.vo.LearningLessonVO;
import com.tianji.learning.domain.vo.LearningPlanPageVO;
import com.tianji.learning.domain.vo.LearningPlanVO;
import com.tianji.learning.enums.LessonStatus;
import com.tianji.learning.enums.PlanStatus;
import com.tianji.learning.mapper.LearningLessonMapper;
import com.tianji.learning.service.ILearningLessonService;
import com.tianji.learning.service.ILearningRecordService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 学生课程表 服务实现类
 * </p>
 *
 * @author xjs
 */
@Slf4j
@Service
public class LearningLessonServiceImpl extends ServiceImpl<LearningLessonMapper, LearningLesson> implements ILearningLessonService {

    @Autowired
    private CourseClient courseClient;

    @Autowired
    private CatalogueClient catalogueClient;

    @Autowired
    private ILearningRecordService recordService;

    @Override
    public LearningLessonVO queryLessonByCourseId(Long courseId) {
        // 1.获取当前登录用户
        Long userId = UserContext.getUser();
        // 2.查询课程信息 select * from xx where user_id = #{userId} AND course_id = #{courseId}
        LearningLesson lesson = getOne(buildUserIdAndCourseIdWrapper(userId, courseId));
        if (lesson == null) {
            return null;
        }
        // 3.处理VO
        return BeanUtils.copyBean(lesson, LearningLessonVO.class);
    }

    private LambdaQueryWrapper<LearningLesson> buildUserIdAndCourseIdWrapper(Long userId, Long courseId) {
        LambdaQueryWrapper<LearningLesson> queryWrapper = new QueryWrapper<LearningLesson>()
                .lambda()
                .eq(LearningLesson::getUserId, userId)
                .eq(LearningLesson::getCourseId, courseId);
        return queryWrapper;
    }

    @Override
    public LearningPlanPageVO queryMyPlans(PageQuery query) {
        LearningPlanPageVO vo = new LearningPlanPageVO();
        Long userId = UserContext.getUser();
        // 本周已学完小节数量 learning_record
        LocalDate now = LocalDate.now();
        LocalDateTime begin = DateUtils.getWeekBeginTime(now);
        LocalDateTime end = DateUtils.getWeekEndTime(now);
        LambdaQueryWrapper<LearningRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .eq(LearningRecord::getUserId, userId)
                .eq(LearningRecord::getFinished, true)
                .between(LearningRecord::getFinishTime, begin, end);
        int weekFinished =recordService.count(queryWrapper);
        vo.setWeekFinished(weekFinished);
        // 本周计划学习小节数量 learning_lesson
        int weekPlanTotal = this.getBaseMapper().queryPlanWeekFreq(userId);
        vo.setWeekTotalPlan(weekPlanTotal);
        // 分页查课表  learning_lesson
        LambdaQueryWrapper<LearningLesson> lessonWrapper = new LambdaQueryWrapper<>();
        lessonWrapper.eq(LearningLesson::getUserId, userId);
        lessonWrapper.in(LearningLesson::getStatus, Arrays.asList(0,1,2));
        lessonWrapper.eq(LearningLesson::getPlanStatus, PlanStatus.PLAN_RUNNING.getValue());
        IPage<LearningLesson> page = this.page(new Page<>(query.getPageNo(), query.getPageSize()), lessonWrapper);
        List<LearningLesson> records = page.getRecords();
        if(CollUtil.isEmpty(records)){
            return vo;
        }
        // 查询课程信息
        List<Long> courseIds = records.stream().map(LearningLesson::getCourseId).distinct().collect(Collectors.toList());
        List<CourseSimpleInfoDTO> courseList = courseClient.getSimpleInfoList(courseIds);
        if(CollUtil.isEmpty(courseList)){
            throw new BizIllegalException("course empty");
        }
        // 查询用户本周每门课已学习的小节数量
        List<IdAndNumDTO> idAndNumDTOS = recordService.queryFinishedSectionNum(userId, begin, end);
        //  填充本周每门课已学习的小节数量，learning_record
        List<LearningPlanVO> list = new ArrayList<>();
        for (LearningLesson record : records) {
            LearningPlanVO planVO = BeanUtils.copyBean(record, LearningPlanVO.class);
            // 从所有的课courseList中找到当前课
            CourseSimpleInfoDTO course = findCourse(courseList,record.getCourseId());
            if(course == null){
                throw new BizIllegalException("course empty");
            }
            planVO.setCourseName(course.getName());
            planVO.setSections(course.getSectionNum());
            // 从所有的 课和已学数量idAndNumDTOS 中找到当前课的已学数量
            IdAndNumDTO idAndNumDTO = findWeekLearnedSections(idAndNumDTOS, record.getId());
            planVO.setWeekLearnedSections(idAndNumDTO==null?0:idAndNumDTO.getNum());
            list.add(planVO);
        }
        vo.setList(list);
        return vo;
    }

    private IdAndNumDTO findWeekLearnedSections(List<IdAndNumDTO> idAndNumDTOS, Long id) {
        if(CollUtil.isEmpty(idAndNumDTOS)){
            return null;
        }
        for (IdAndNumDTO idAndNumDTO : idAndNumDTOS){
            if(idAndNumDTO.getId().equals(id)){
                return idAndNumDTO;
            }
        }
        return null;
    }

    @Override
    public void createLearningPlan(Long courseId, Integer freq) {
        Long userId = UserContext.getUser();
        // 根据courseid和userid查询课表
        LambdaQueryWrapper<LearningLesson> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(LearningLesson::getUserId, userId);
        queryWrapper.eq(LearningLesson::getCourseId, courseId);
        LearningLesson lesson = this.getOne(queryWrapper);
        if(lesson == null){
            throw new BizIllegalException("lesson empty");
        }
        // 更新每周学习频率 计划的状态
        lesson.setWeekFreq(freq);
        lesson.setPlanStatus(PlanStatus.PLAN_RUNNING.getValue());
        this.updateById(lesson);
    }

    @Override
    public LearningLesson queryByUserIdCourseId(Long userId, Long courseId) {
        LambdaQueryWrapper<LearningLesson> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(LearningLesson::getUserId, userId);
        queryWrapper.eq(LearningLesson::getCourseId, courseId);
        return this.getOne(queryWrapper);
    }

    @Override
    public Long isLessonValid(Long courseId) {
        Long userId = UserContext.getUser();
        // 查用户的课表
        LearningLesson lesson = this.lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                .eq(LearningLesson::getCourseId, courseId).one();
        if(lesson == null){
            return null;
        }
        // 判断状态
        Integer status = lesson.getStatus();
        if(status == LessonStatus.EXPIRED.getValue()){
            return null;
        }
        return lesson.getId();
    }

    @Override
    public LearningLessonVO queryMyCurrentLesson() {
        Long userId = UserContext.getUser();
        // 查询最近学习的课表 latest_learn_time 降序取第一条
        LearningLesson lessonDB = this.lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                .eq(LearningLesson::getStatus, LessonStatus.LEARNING.getValue())
                .orderByDesc(LearningLesson::getLatestLearnTime)
                .last(" limit 1")
                .one();
        if(lessonDB == null){
            return  null;
        }
        LearningLessonVO vo = BeanUtils.copyBean(lessonDB, LearningLessonVO.class);
        // 根据courseId 取 course
        List<CourseSimpleInfoDTO> courseList = courseClient.getSimpleInfoList(Arrays.asList(lessonDB.getCourseId()));
        if(CollUtil.isEmpty(courseList)){
            throw new BizIllegalException("查询不到课程信息, id:" +lessonDB.getCourseId());
        }
        CourseSimpleInfoDTO course = courseList.get(0);
        vo.setCourseName(course.getName());
        vo.setCourseCoverUrl(course.getCoverUrl());
        vo.setSections(course.getSectionNum());
        // 根据latest_section_id 取小节的信息
        List<CataSimpleInfoDTO> catalogueList = catalogueClient.batchQueryCatalogue(Arrays.asList(lessonDB.getLatestSectionId()));
        if(CollUtil.isEmpty(catalogueList)) {
            throw new BizIllegalException("查询不到章节信息, id:" +lessonDB.getLatestSectionId());
        }
        CataSimpleInfoDTO catalogue = catalogueList.get(0);
        vo.setLatestSectionName(catalogue.getName());
        vo.setLatestSectionIndex(catalogue.getCIndex());
        // 查询总的加入到课表的课程数量
        Integer count = this.lambdaQuery().eq(LearningLesson::getUserId, userId).count();
        vo.setCourseAmount(count);
        return vo;
    }

    @Override
    public PageDTO<LearningLessonVO> queryMyLessons(PageQuery query) {
        Long userId = UserContext.getUser();
        // userid 分页 排序
        String sortBy = query.getSortBy();
        Boolean isAsc = query.getIsAsc();
        if(StringUtils.isEmpty(sortBy)){
            sortBy = "latest_learn_time";
            isAsc = false;
        }
        Page<LearningLesson> page = this.lambdaQuery().eq(LearningLesson::getUserId, userId).page(query.toMpPage(sortBy, isAsc));
        List<LearningLesson> records = page.getRecords();
        if(CollUtil.isEmpty(records)){
            return PageDTO.empty(page);
        }
        // 搜集courseIds -> course
        List<Long> courseIds = records.stream().map(LearningLesson::getCourseId).distinct().collect(Collectors.toList());
        List<CourseSimpleInfoDTO> courseList = courseClient.getSimpleInfoList(courseIds);
        if(CollUtil.isEmpty(courseList)){
            throw  new BizIllegalException("查询不到课程信息" );
        }
        // fill
        List<LearningLessonVO> voList = new ArrayList<>();
        for (LearningLesson record : records) {
            LearningLessonVO vo = BeanUtils.copyBean(record, LearningLessonVO.class);
            CourseSimpleInfoDTO course = findCourse(courseList, record.getCourseId());
            if(course == null){
                throw  new BizIllegalException("查询不到课程信息" );
            }
            vo.setCourseName(course.getName());
            vo.setCourseCoverUrl(course.getCoverUrl());
            vo.setSections(course.getSectionNum());
            voList.add(vo);
        }
        return PageDTO.of(page, voList);
    }

    private CourseSimpleInfoDTO findCourse(List<CourseSimpleInfoDTO> courseList, Long courseId) {
        for (CourseSimpleInfoDTO courseSimpleInfoDTO : courseList) {
            if(Objects.equals(courseSimpleInfoDTO.getId(), courseId)){
                return courseSimpleInfoDTO;
            }
        }
        return null;
    }

    @Override
    public void addCourseToLesson(Long userId, List<Long> courseIds) {
        if(userId == null || CollUtil.isEmpty(courseIds)){
            log.error("message illegal" );
            return;
        }
        //  courseIds -> course
        List<CourseSimpleInfoDTO> courseList = courseClient.getSimpleInfoList(courseIds);
        if(CollUtil.isEmpty(courseList)){
            log.error("查询不到课程信息" );
            return;
        }
        List<LearningLesson> lessonList = new ArrayList<>(courseList.size());
        for (CourseSimpleInfoDTO courseSimpleInfoDTO : courseList) {
            LearningLesson lesson = new LearningLesson();
            lesson.setUserId(userId);
            lesson.setCourseId(courseSimpleInfoDTO.getId());
            // 有效期
            Integer validDuration = courseSimpleInfoDTO.getValidDuration();
            if(validDuration != null){
                LocalDateTime expireDate = LocalDateTime.now().plusMonths(validDuration);
                lesson.setExpireTime(expireDate);
            }
            lessonList.add(lesson);
        }
        // save
        saveBatch(lessonList);
    }
}
